package com.hclc.yxb.shiro;

import com.hclc.config.util.TokenUtil;
import com.hclc.entity.model.enums.PortTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.SimpleSession;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;


/**
 * @author lixin
 * @version V1.0
 * @ClassName: MySessionDAO
 * @Description: TODO(MySessionDAO)
 * @date 2019年7月17日 上午10:26:12
 */
@Component
@Slf4j
public class MySessionDAO extends AbstractSessionDAO {

    /**
     * token过期时间(分钟)
     */
    private final long TIME_OUT = 60;

    /**
     * session的redisKey
     */
    public static final String sessionIdsKey = "SESSION-ID-";


//    private ConcurrentMap<Serializable, Session> sessions;

    @Resource(name = "shiroRedisTemplate")
    private RedisTemplate<String, Object> redisTemplate;

//    public MySessionDAO() {
//        this.sessions = new ConcurrentHashMap<>();
//    }

    @Override
    protected Serializable doCreate(Session session) {
        Serializable sessionId = generateSessionId(session);        // 生成sessionId
        String token = sessionId.toString().replaceAll("-", "");
        sessionId = TokenUtil.formatToken(token, PortTypeEnum.BACKSTAGE);
        assignSessionId(session, sessionId);                        // 将sessionId赋值到session
        saveSession(sessionId, session);                            // 存储session到sessions
        return sessionId;
    }

//    // 存储session到sessions
//    protected Session storeSession(Serializable id, Session session) {
//        if (id == null) {
//            throw new NullPointerException("id argument cannot be null.");
//        }
//        return sessions.putIfAbsent(id, session);
//    }

    /**
     * 将session序列化到redis
     *
     * @param id
     * @param session
     * @return void
     * @Description: TODO(将session序列化到redis)
     * @author hef
     * @version 2.0
     * @date 2020/9/23 2:22 下午
     */
    protected void saveSession(Serializable id, Session session) {
        if (id == null) {
            throw new NullPointerException("id argument cannot be null.");
        }
        redisTemplate.opsForValue().set(sessionIdsKey + id.toString(), session, TIME_OUT, TimeUnit.MINUTES);
    }

    protected void delSession(Serializable id) {
        if (id == null) {
            throw new NullPointerException("id argument cannot be null.");
        }
        redisTemplate.delete(sessionIdsKey + id);
    }

    protected Session getSession(Serializable id) {
        return (SimpleSession) redisTemplate.opsForValue().get(sessionIdsKey + id);
    }

    @Override
    protected Session doReadSession(Serializable sessionId) {
//        return sessions.get(sessionId);
        return getSession(sessionId);
    }

    @Override
    public void update(Session session) throws UnknownSessionException {
//        storeSession(session.getId(), session);
        saveSession(session.getId(), session);
    }

    @Override
    public void delete(Session session) {
        if (session == null) {
            throw new NullPointerException("session argument cannot be null.");
        }
        Serializable id = session.getId();
        if (id != null) {
//            sessions.remove(id);
            delSession(id);
        }
    }

    @Override
    public Collection<Session> getActiveSessions() {
        Set<Session> sessions = new HashSet<>();
        Set<String> keys = redisTemplate.keys(sessionIdsKey + "*");
        keys.stream().forEach(s -> {
            sessions.add(getSession(s));
        });
        return sessions;
//        Collection<Session> values = sessions.values();
//        if (CollectionUtils.isEmpty(values)) {
//            return Collections.emptySet();
//        } else {
//            return Collections.unmodifiableCollection(values);
//        }

    }
}
